package org.jeecg.modules.iot.middleware.processor.control;

import org.jeecg.modules.rental.entity.RentalEBike;
import org.jeecg.modules.iot.model.control.CentralControlConfig;
import org.jeecg.modules.iot.model.control.SpeedOtherConfig;
import org.jeecg.modules.iot.model.modbus.ModbusParams;
import org.jeecg.modules.iot.middleware.processor.JT808Processor;
import org.jeecg.modules.iot.middleware.processor.MessageType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class ControlService {

    @Autowired
    private JT808Processor jt808Processor;


    public String queryControl(RentalEBike car) {
        // 创建 Modbus 参数对象
        ModbusParams modbusParams = new ModbusParams();

        // 设置从机地址为 0x03 (BMS 的地址)
        modbusParams.setSlaveAddress(0x04);

        // 设置起始寄存器地址为 0xA310
        modbusParams.setStartAddress(0xA100);


        //设置查询寄存器个数
        modbusParams.setRegisterCount(32);

        // 设置功能码为写入多个寄存器
        modbusParams.setFunctionCode(ModbusParams.FunctionCode.READ_HOLDING_REGISTERS);


        // 调用 jt808Processor 发送 Modbus 请求
        String mqttJson = jt808Processor.processTransparentMqttJson(car, MessageType.QUERY_CONTROL, modbusParams);

        // 如果请求成功，返回 true，否则返回 false
        return mqttJson;
    }


    public int setSpeed(RentalEBike car, SpeedOtherConfig speedOtherConfig) {
        // 创建 Modbus 参数对象
        ModbusParams modbusParams = new ModbusParams();

        // 设置从机地址为 0x03 (控制器 的地址)
        modbusParams.setSlaveAddress(0x04);

        // 设置起始寄存器地址为 0xA100
        modbusParams.setStartAddress(0xA100);

        // 生成要写入的寄存器值
        int newValue = generateNewValue(speedOtherConfig);

        // 设置要写入的值
        modbusParams.setValues(new int[]{newValue});

        // 设置查询寄存器个数
        modbusParams.setRegisterCount(1);

        // 设置功能码为写入多个寄存器
        modbusParams.setFunctionCode(ModbusParams.FunctionCode.WRITE_MULTIPLE_REGISTERS);

        // 调用 jt808Processor 发送 Modbus 请求
        Integer seq = jt808Processor.processTransparent(car, MessageType.SETTING_CONTROL, modbusParams);

        return seq;
    }

    // 生成新的寄存器值
    private int generateNewValue(SpeedOtherConfig config) {
        int newValue = 0;

        // 设置高八位
        newValue |= (config.getWorkMode().getValue() << 6) & 0xC0; // bit7~bit6 工作模式
        newValue |= (config.getStartMode().getValue() << 5) & 0x20; // bit5 启动模式
        newValue |= (config.getAssistLevel() << 2) & 0x1C; // bit4~bit2 助力等级
        newValue |= (config.isMotorLock() ? 1 : 0) << 1; // bit1 锁电机信号
        newValue |= (config.isPowerDisable() ? 1 : 0); // bit0 动力禁用使能

        // 设置低八位速度值
        newValue <<= 8; // 将高八位移到高字节
        newValue |= config.getSpeed(); // 设置低八位速度值

        return newValue;
    }

    /*0xA103	1	Uint8（高）	厘米	轮径（RW）（记录车辆的参数）
        Uint8（低）	一个物理按键上传
        定义一个按键，读的状态，绑定
        J8-4 	控制器上报事件类型
                位段说明
        内容说明

                bit7（RW）	一键还车按下。
        1：按下，
        0：未按下。
        主机查询到一键还车按下标识后，如果可以正常还车则进行还车操作后清除按下标识*/
    public int setWheelDiameter(RentalEBike car, int wheelDiameter) {
        // 创建 Modbus 参数对象
        ModbusParams modbusParams = new ModbusParams();

        // 设置从机地址为 0x04 (控制器 的地址)
        modbusParams.setSlaveAddress(0x04);

        // 设置起始寄存器地址为 0xA103
        modbusParams.setStartAddress(0xA103);

        // 读取当前寄存器的值
        int currentValue = queryControlValue(car, 0xA103);

        // 保留低字节的按键状态，只修改高字节的轮径值
        int newValue = (wheelDiameter << 8) | (currentValue & 0xFF);

        int[] values = new int[]{newValue};
        modbusParams.setValues(values);

        // 设置查询寄存器个数
        modbusParams.setRegisterCount(1);

        // 设置功能码为写入多个寄存器
        modbusParams.setFunctionCode(ModbusParams.FunctionCode.WRITE_MULTIPLE_REGISTERS);

        // 调用 jt808Processor 发送 Modbus 请求
        return jt808Processor.processTransparent(car, MessageType.SETTING_CONTROL, modbusParams);
    }

    /*0xA105	1	Uint16	KM	预估剩余里程RW（不用管）*/
    public int setEstimatedRemainingMileage(RentalEBike car, int mileage) {
        return sendModbusRequest(car, 0x04, 0xA105, 1, ModbusParams.FunctionCode.WRITE_MULTIPLE_REGISTERS, new int[]{mileage}, MessageType.SETTING_CONTROL);
    }

    /*0xA109*/
    public int setPolePairNumber(RentalEBike car, int polePairNumber) {
        return sendModbusRequest(car, 0x04, 0xA109, 1, ModbusParams.FunctionCode.WRITE_MULTIPLE_REGISTERS, new int[]{polePairNumber}, MessageType.SETTING_CONTROL);
    }

    /*0xA10A*/
    public int setTailLightConfig(RentalEBike car, boolean lightOn, boolean blinkMode, int blinkTimes) {
        // 创建 Modbus 参数对象
        ModbusParams modbusParams = new ModbusParams();

        // 设置从机地址为 0x04 (控制器 的地址)
        modbusParams.setSlaveAddress(0x04);

        // 设置起始寄存器地址为 0xA10A
        modbusParams.setStartAddress(0xA10A);

        // 设置要写入的值
        int newValue = 0;

        // Bit2: 大灯开关
        newValue |= (lightOn ? 1 : 0) << 2;

        // Bit1: 闪烁模式 (true 为闪烁，false 为常亮)
        newValue |= (blinkMode ? 1 : 0) << 1;

        // Bit0: 关灯 (默认值，无需设置)

        // 低字节：闪烁次数
        newValue <<= 8;
        newValue |= (blinkTimes & 0xFF);  // 确保闪烁次数在 0-255 之间

        int[] values = new int[]{newValue};
        modbusParams.setValues(values);

        // 设置查询寄存器个数
        modbusParams.setRegisterCount(1);

        // 设置功能码为写入多个寄存器
        modbusParams.setFunctionCode(ModbusParams.FunctionCode.WRITE_MULTIPLE_REGISTERS);

        // 调用 jt808Processor 发送 Modbus 请求
        return jt808Processor.processTransparent(car, MessageType.SETTING_CONTROL, modbusParams);
    }

    /*0xA10D*/
    public int setBatteryVoltageAndCurrentLimit(RentalEBike car, int batteryVoltageType, int currentLimit) {
        int combinedValue = (batteryVoltageType << 8) | (currentLimit & 0xFF);
        return sendModbusRequest(
                car,
                0x04,
                0xA10D,
                1,
                ModbusParams.FunctionCode.WRITE_MULTIPLE_REGISTERS,
                new int[]{combinedValue},
                MessageType.SETTING_CONTROL
        );
    }

    /*0xA10E*/
    public int setCentralControlConfig(RentalEBike car, CentralControlConfig config) {
        // 创建 Modbus 参数对象
        ModbusParams modbusParams = new ModbusParams();


        // 设置功能码为写入多个寄存器
        modbusParams.setFunctionCode(ModbusParams.FunctionCode.WRITE_MULTIPLE_REGISTERS);

        // 设置从机地址为 0x03 (BMS 的地址)
        modbusParams.setSlaveAddress(0x04);

        // 设置起始寄存器地址为 0xA10E
        modbusParams.setStartAddress(0xA10E);

        // 设置要写入的值
        int newValue = 0;

        // 设置 Bit0: 国标/解速
        newValue |= (config.speedLimitEnabled ? 1 : 0) << 0; // 修正

        // 设置 Bit1: 联动功能
        newValue |= (config.linkageEnabled ? 1 : 0) << 1;

        // 设置 Bit2: 备用 (默认 0)
        // newValue |= 0 << 2; // 不需要显式设置，因为默认值为 0

        // 设置 Bit3: EABS
        newValue |= (config.eabsEnabled ? 1 : 0) << 3;

        // 设置 Bit4-Bit6: 停车进入 P 档时间
        newValue |= (config.getParkingToPTime() & 0x07) << 4; // 修正

        // 设置 Bit7: 防陡坡
        newValue |= (config.slopePreventionEnabled ? 1 : 0) << 7;

        // 设置 Bit8: TCS
        newValue |= (config.tcsEnabled ? 1 : 0) << 8;

        // 设置 Bit9-Bit10: 启动档位
        newValue |= (config.getStartGear() & 0x03) << 9; // 保证启动档位在 0-3 之间

        // 设置 Bit11-Bit15: 软启动等级
        newValue |= (config.softStartLevel & 0x1F) << 11; // 保证软启动等级在 0-31 之间

        int[] values = new int[]{newValue};
        modbusParams.setValues(values);

        // 调用 jt808Processor 发送 Modbus 请求
        Integer seq = jt808Processor.processTransparent(car, MessageType.SETTING_CONTROL, modbusParams);

        return seq;
    }

    /*0xA10E*/
    public int setCentralControlConfigOld(RentalEBike car, CentralControlConfig config) {
        // 创建 Modbus 参数对象
        ModbusParams modbusParams = new ModbusParams();

        // 设置从机地址为 0x03 (BMS 的地址)
        modbusParams.setSlaveAddress(0x04);

        // 设置起始寄存器地址为 0xA10E
        modbusParams.setStartAddress(0xA10E);

        // 设置要写入的值
        int newValue = 0;

        // 设置 Bit0: 软启动
        newValue |= (config.softStartEnabled ? 1 : 0) << 0;

        // 设置 Bit1: 联动功能
        newValue |= (config.linkageEnabled ? 1 : 0) << 1;

        // 设置 Bit3: EABS
        newValue |= (config.eabsEnabled ? 1 : 0) << 3;

        // 设置 Bit7: 防陡坡
        newValue |= (config.slopePreventionEnabled ? 1 : 0) << 7;

        // 设置 Bit8: TCS
        newValue |= (config.tcsEnabled ? 1 : 0) << 8;


        // 设置 Bit9-Bit14: 软启动等级
        newValue |= (config.softStartLevel & 0x3F) << 9; // 保证软启动等级在 0-31 之间

        // 设置 Bit15: 国标/解速
        newValue |= (config.speedLimitEnabled ? 0 : 1) << 15;

        int[] values = new int[]{newValue};
        modbusParams.setValues(values);

        // 设置查询寄存器个数
        modbusParams.setRegisterCount(1);

        // 设置功能码为写入多个寄存器
        modbusParams.setFunctionCode(ModbusParams.FunctionCode.WRITE_MULTIPLE_REGISTERS);

        // 调用 jt808Processor 发送 Modbus 请求
        Integer seq = jt808Processor.processTransparent(car, MessageType.SETTING_CONTROL, modbusParams);

        return seq;
    }


    /*0xA10E*/
    public Boolean enableSportMode(RentalEBike car ,Boolean enable ) {
        // 创建 Modbus 参数对象
        ModbusParams modbusParams = new ModbusParams();
        modbusParams.setFunctionCode(ModbusParams.FunctionCode.WRITE_MULTIPLE_REGISTERS);
        modbusParams.setSlaveAddress(0x04);
        modbusParams.setStartAddress(0xA10E);
        CentralControlConfig config =new CentralControlConfig();
        // 根据 enableSportMode 设置配置
            if (enable){
                config.setSoftStartEnabled(true);
                config.setLinkageEnabled(true);
                config.setEabsEnabled(true);
                config.setSlopePreventionEnabled(true);
                config.setTcsEnabled(true);
                config.setSoftStartLevel(3); // 运动模式软启动等级
                config.setSpeedLimitEnabled(false); // 运动模式取消限速
                config.setStartGear(2); // 运动模式启动档位
                config.setParkingToPTime(1); // 运动模式停车P档时间
            }else {
                config.setSoftStartEnabled(true);
                config.setLinkageEnabled(false);
                config.setEabsEnabled(true);
                config.setSlopePreventionEnabled(true);
                config.setTcsEnabled(true);
                config.setSoftStartLevel(3); // 运动模式软启动等级
                config.setSpeedLimitEnabled(true); // 运动模式取消限速
                config.setStartGear(2); // 运动模式启动档位
                config.setParkingToPTime(1); // 运动模式停车P档时间
            }



        // 计算要写入的值  --  提取为独立方法提高可读性
        int newValue = calculateRegisterValue(config);
        modbusParams.setValues(new int[]{newValue});

        // 调用 jt808Processor 发送 Modbus 请求
         jt808Processor.processTransparent(car, MessageType.SETTING_CONTROL, modbusParams);
        return true;
    }


    private int calculateRegisterValue(CentralControlConfig config) {
        int newValue = 0;
        newValue |= (config.isSpeedLimitEnabled() ? 1 : 0);  // Bit 0:  Simplified boolean handling
        newValue |= (config.isLinkageEnabled() ? 1 : 0) << 1;
        newValue |= (config.isEabsEnabled() ? 1 : 0) << 3;
        newValue |= (config.getParkingToPTime() & 0x07) << 4; // Ensure value is within range
        newValue |= (config.isSlopePreventionEnabled() ? 1 : 0) << 7;
        newValue |= (config.isTcsEnabled() ? 1 : 0) << 8;
        newValue |= (config.getStartGear() & 0x03) << 9;      // Ensure value is within range
        newValue |= (config.getSoftStartLevel() & 0x1F) << 11; // Ensure value is within range
        return newValue;
    }

    /*0xA10F  1	Uint16	0.1	用于配置车辆欠压保护电压	单位0.1V*/
    public int setUndervoltageProtection(RentalEBike car, float undervoltageProtection) {
        int undervoltageProtectionValue = (int) (undervoltageProtection * 10);
        return sendModbusRequest(car, 0x04, 0xA10F, 1, ModbusParams.FunctionCode.WRITE_MULTIPLE_REGISTERS, new int[]{undervoltageProtectionValue}, MessageType.SETTING_CONTROL);
    }


    /*0xA110	1	Uint16
    Bit0	刹车能回收开关（0关1开）默认1
    Bit1	转吧刹车能开关（0关1开）默认0
    Bit2	刹把解P
    Bit4---Bit9（可以分步开发）	刹车能回收强度中控配置控制器    0表示不回收 默认为0  （0-5）SOC 小于90回收，无SOC或SOC为100不回收
    Bit10---Bit12	助力强度   6档  默认111档
    000（关闭助力）   001  011  111  110   100
      按键J16-4  J16-5  4加5减档
    Bit13	转吧定速开启
    Bit14	按键定速开启
    Bit15	备用*/
    public int setBrakeAndAssistConfig(RentalEBike car, boolean brakeEnergyRecoveryEnabled, boolean handleBrakeEnergyRecoveryEnabled, boolean handleReleasePowerEnabled, int recoveryIntensity, int assistIntensity, boolean handleCruiseControlEnabled, boolean buttonCruiseControlEnabled) {
        // 创建 Modbus 参数对象
        ModbusParams modbusParams = new ModbusParams();

        // 设置从机地址为 0x04 (控制器 的地址)
        modbusParams.setSlaveAddress(0x04);

        // 设置起始寄存器地址为 0xA110
        modbusParams.setStartAddress(0xA110);

        // 读取当前寄存器的值
        int currentValue = queryControlValue(car, 0xA110);

        // 设置要写入的值
        int newValue = currentValue;

        // 设置 Bit0: 刹车能回收开关
        newValue &= ~(1 << 0); // 清除 Bit0
        newValue |= (brakeEnergyRecoveryEnabled ? 1 : 0) << 0;

        // 设置 Bit1: 转吧刹车能开关
        newValue &= ~(1 << 1); // 清除 Bit1
        newValue |= (handleBrakeEnergyRecoveryEnabled ? 1 : 0) << 1;

        // 设置 Bit2: 刹把解P
        newValue &= ~(1 << 2); // 清除 Bit2
        newValue |= (handleReleasePowerEnabled ? 1 : 0) << 2;

        // 设置 Bit4-Bit9: 刹车能回收强度
        newValue &= ~(0x3F << 4); // 清除 Bit4-Bit9
        newValue |= (recoveryIntensity & 0x3F) << 4; // 保证回收强度在 0-63 之间

        // 设置 Bit10-Bit12: 助力强度
        newValue &= ~(0x07 << 10); // 清除 Bit10-Bit12
        newValue |= (assistIntensity & 0x07) << 10; // 保证助力强度在 0-7 之间

        // 设置 Bit13: 转吧定速开启
        newValue &= ~(1 << 13); // 清除 Bit13
        newValue |= (handleCruiseControlEnabled ? 1 : 0) << 13;

        // 设置 Bit14: 按键定速开启
        newValue &= ~(1 << 14); // 清除 Bit14
        newValue |= (buttonCruiseControlEnabled ? 1 : 0) << 14;

        // 设置 Bit15: 备用位 (默认 0)
        newValue &= ~(1 << 15); // 清除 Bit15

        int[] values = new int[]{newValue};
        modbusParams.setValues(values);

        // 设置查询寄存器个数
        modbusParams.setRegisterCount(1);

        // 设置功能码为写入多个寄存器
        modbusParams.setFunctionCode(ModbusParams.FunctionCode.WRITE_MULTIPLE_REGISTERS);

        // 调用 jt808Processor 发送 Modbus 请求
        return jt808Processor.processTransparent(car, MessageType.SETTING_CONTROL, modbusParams);
    }


    /*0xA111	1	Uint16	次	刹车累计次数，本次上电。（R）*/
    public int getBrakeCount(RentalEBike car) {
        return sendModbusReadRequest(car, 0x04, 0xA111, 1, ModbusParams.FunctionCode.READ_HOLDING_REGISTERS, MessageType.QUERY_CONTROL);
    }

    /*0xA112	1	Uint16	秒	累计刹车时长，本次上电。（R）*/
    public int getBrakeDuration(RentalEBike car) {
        return sendModbusReadRequest(car, 0x04, 0xA112, 1, ModbusParams.FunctionCode.READ_HOLDING_REGISTERS, MessageType.QUERY_CONTROL);
    }

    /*0xA113	1	Uint8（高）	~	低速（1）（百分之    XX）
    Uint8（低）		高速（3） （百分之 一百X）*/
    public int getSpeedPercentage(RentalEBike car) {
        return sendModbusReadRequest(car, 0x04, 0xA113, 1, ModbusParams.FunctionCode.READ_HOLDING_REGISTERS, MessageType.QUERY_CONTROL);
    }

    /*0xA113	1	Uint8（高）	~	一档（1）（百分之    XX）
		Uint8（低）		二档（3） （百分之   XX）*/
    public int setSpeedPercentages(RentalEBike car, int gear1Percentage, int gear2Percentage) {
        // 创建 Modbus 参数对象
        ModbusParams modbusParams = new ModbusParams();


        // 设置从机地址为 0x04 (控制器 的地址)
        modbusParams.setSlaveAddress(0x04);

        // 设置起始寄存器地址为 0xA113
        modbusParams.setStartAddress(0xA113);

        // 设置要写入的值
        int newValue = (gear1Percentage & 0xFF) << 8 | (gear2Percentage & 0xFF);

        int[] values = new int[]{newValue};
        modbusParams.setValues(values);

        // 设置查询寄存器个数
        modbusParams.setRegisterCount(1);

        // 设置功能码为写入多个寄存器
        modbusParams.setFunctionCode(ModbusParams.FunctionCode.WRITE_MULTIPLE_REGISTERS);

        // 调用 jt808Processor 发送 Modbus 请求
        return jt808Processor.processTransparent(car, MessageType.SETTING_CONTROL, modbusParams);
    }

    private int sendModbusReadRequest(RentalEBike car, int slaveAddress, int startAddress, int registerCount, ModbusParams.FunctionCode functionCode, MessageType messageType) {
        ModbusParams modbusParams = new ModbusParams();
        modbusParams.setSlaveAddress(slaveAddress);
        modbusParams.setStartAddress(startAddress);
        modbusParams.setRegisterCount(registerCount);
        modbusParams.setFunctionCode(functionCode);
        return jt808Processor.processTransparent(car, messageType, modbusParams);
    }

    private int sendModbusRequest(RentalEBike car, int slaveAddress, int startAddress, int registerCount, ModbusParams.FunctionCode functionCode, int[] values, MessageType messageType) {
        ModbusParams modbusParams = new ModbusParams();
        modbusParams.setSlaveAddress(slaveAddress);
        modbusParams.setStartAddress(startAddress);
        modbusParams.setRegisterCount(registerCount);
        modbusParams.setFunctionCode(functionCode);
        if (values != null) {
            modbusParams.setValues(values);
        }
        return jt808Processor.processTransparent(car, messageType, modbusParams);
    }

    public boolean isReturnButtonClicked(RentalEBike car) {
        // 读取 0xA103 寄存器的值
        int registerValue = queryControlValue(car, 0xA103);

        // 检查 Bit7 是否为 1
        return (registerValue & (1 << 7)) != 0;
    }

    public void clearReturnButtonClick(RentalEBike car) {
        // 创建 Modbus 参数对象
        ModbusParams modbusParams = new ModbusParams();

        // 设置从机地址为 0x04 (控制器 的地址)
        modbusParams.setSlaveAddress(0x04);

        // 设置起始寄存器地址为 0xA103
        modbusParams.setStartAddress(0xA103);

        // 读取当前寄存器的值
        int currentValue = queryControlValue(car, 0xA103);

        // 清除 Bit7
        int newValue = currentValue & ~(1 << 7);

        int[] values = new int[]{newValue};
        modbusParams.setValues(values);

        // 设置查询寄存器个数
        modbusParams.setRegisterCount(1);

        // 设置功能码为写入多个寄存器
        modbusParams.setFunctionCode(ModbusParams.FunctionCode.WRITE_MULTIPLE_REGISTERS);

        // 调用 jt808Processor 发送 Modbus 请求
        jt808Processor.processTransparent(car, MessageType.SETTING_CONTROL, modbusParams);
    }

    // 假设你有一个方法可以读取寄存器的值
    private int queryControlValue(RentalEBike car, int startAddress) {
        // ... 实现读取寄存器值的逻辑
        // ... 例如，你可以使用 ModbusParams.FunctionCode.READ_HOLDING_REGISTERS 功能码读取寄存器值
        return 0; // 返回读取到的值
    }

    public String queryControlByaddress(RentalEBike car, String address) {
        // 创建 Modbus 参数对象
        ModbusParams modbusParams = new ModbusParams();

        // 设置从机地址为 0x03 (BMS 的地址)
        modbusParams.setSlaveAddress(0x04);


        switch (address) {
            case "0xA109":
                modbusParams.setStartAddress(0xA109);
                //设置查询寄存器个数
                modbusParams.setRegisterCount(1);

        }
        // 设置起始寄存器地址为 0xA310

        // 设置功能码为读取多个寄存器
        modbusParams.setFunctionCode(ModbusParams.FunctionCode.READ_HOLDING_REGISTERS);


        // 调用 jt808Processor 发送 Modbus 请求
        String mqttJson = jt808Processor.processTransparentMqttJson(car, MessageType.QUERY_CONTROL, modbusParams);

        // 如果请求成功，返回 true，否则返回 false
        return mqttJson;
    }

    public Boolean getSportModeStatus(RentalEBike car) {
        // 创建 Modbus 参数对象
        ModbusParams modbusParams = new ModbusParams();

        // 设置从机地址为 0x03 (BMS 的地址)
        modbusParams.setSlaveAddress(0x04);

        // 设置起始寄存器地址为 0xA310
        modbusParams.setStartAddress(0xA10E);


        //设置查询寄存器个数
        modbusParams.setRegisterCount(32);

        // 设置功能码为写入多个寄存器
        modbusParams.setFunctionCode(ModbusParams.FunctionCode.READ_HOLDING_REGISTERS);


        // 调用 jt808Processor 发送 Modbus 请求
        String mqttJson = jt808Processor.processTransparentMqttJson(car, MessageType.QUERY_CONTROL, modbusParams);

        // 如果请求成功，返回 true，否则返回 false
        return true;
    }
}
